<template>
  <div class="all-page">
    <div class="search">
      <div class="overall-link-condition">
        <a-form layout="inline" :label-col="labelCol" class="form-style">
          <a-form-item label="层级：">
            <a-select
              class="select-style"
              placeholder="请选择"
              v-model="modelLevel"
              @change="modelLevelChange()"
            >
            </a-select>
          </a-form-item>
          <a-form-item label="模型名称：">
            <a-select
              class="select-style"
              :value="modelCode"
              placeholder="请选择"
              allow-clear
              show-search
              :filter-option="false"
              @popupScroll="handlePopupScroll"
              @change="clickLdapOpt"
              @search="filterOpts"
              :not-found-content="null"
              :default-active-first-option="false"
            >
            </a-select>
          </a-form-item>
        </a-form>
        <div class="all-btn">
          <div class="condition-btn" @click="searchData">查询</div>
          <div class="condition-btn gap" @click="clearData()">重置</div>
          <div v-show="status" class="condition-btn gap" @click="returnRoute">
            返回
          </div>
        </div>
      </div>
    </div>
    <div class="page-content">
      <common-loading
        ref="commonLoading"
        class="loading-position"
      ></common-loading>
      <div class="legend">
        <div class="legend-logo">
          <div
            class="legend-logo-item"
            v-for="(item, index) in legend"
            :key="index"
          >
            <div
              :style="{
                border: item.border,
                backgroundColor: item.backGroundColor,
              }"
              class="rectangle"
            ></div>
            <div class="name">{{ item.name }}</div>
          </div>
          <div class="current-tiem">
            {{ "*加工信息截止:  " + currentTime }}
          </div>
        </div>
        <div class="photo-logo">
          <div
            class="photo-logo-item"
            v-for="(item, index) in logoList"
            :key="index"
          >
            <img :src="item.img" alt="" />
            <span>{{ item.name }}</span>
          </div>
        </div>
      </div>
      <div class="process">
        <div class="content" ref="container"></div>
      </div>
    </div>
  </div>
</template>
<script>
import finished from "@/assets/images/finished1.png";
import unfinished from "@/assets/images/unFinished1.png";
import unStart from "@/assets/images/unStart1.png";
import process from "@/assets/images/process1.png";
import delay from "@/assets/images/delay1.png";
import recover from "@/assets/images/recover1.png";
import G6 from "@antv/g6";
import request from "./request";
import { debounce, isEqual } from "lodash";
import CommonLoading from "@/components/Loading-index.vue";
import moment from "moment";
function truncateString(str) {
  let length = 0; //字符串总长度
  let result = ""; //截取的字符串
  let TARGET_VALUE = 16; //要截取的长度

  for (let i = 0; i < str.length; i++) {
    const charCode = str.charCodeAt(i);
    if (charCode >= 0 && charCode <= 128) {
      length += 1;
    } else {
      length += 2;
    }
    if (length <= TARGET_VALUE) {
      result += str[i];
    }
  }

  return {
    length,
    result,
  };
}
const { queryNodeData, getModelLevelData, getModelCodeData } = request;
function getImg(status) {
  if (status === "1") {
    return unStart;
  } else if (status === "2") {
    return process;
  } else if (status === "3") {
    return finished;
  } else if (status === "6") {
    return unfinished;
  } else if (status === "7") {
    return delay;
  } else if (status === "8") {
    return recover;
  } else {
    return unfinished;
  }
}
function getBackGroundColor(modelLevel) {
  if (!modelLevel)
    return {
      bcColor: "#F9FAFD",
      brColor: "#ECEDF3",
    };
  let style = {
    bcColor: "",
    brColor: "",
  };
  switch (modelLevel) {
    case "1":
      style.bcColor = "#E1D2FF";
      style.brColor = "#F22929";
      break;
    case "2":
      style.bcColor = "#FFEDDB";
      style.brColor = "#FFC510";
      break;
    case "3":
      style.bcColor = "#D0F2D9";
      style.brColor = "#02B32E";
      break;
    case "4":
      style.bcColor = "#C6E3FF";
      style.brColor = "#1890FF";
      break;
  }
  return style;
}
G6.registerNode(
  "card-node",
  {
    draw: (cfg, group) => {
      const img = getImg(cfg.nodeStatus);
      const backGrounfColor = getBackGroundColor(cfg.modelLevel).bcColor;
      const borderColor = getBackGroundColor(cfg.modelLevel).brColor;
      let displayStatus = cfg?.displayStatus || false;
      const len = cfg.cornerMarkNum;
      const rLen = len > 999 ? 15 : 13;
      const xPosition =
        len > 0 && len < 10
          ? 218
          : len > 9 && len < 100
          ? 215
          : len > 99 && len < 1000
          ? 211
          : 208;
      const x = 222 / 2;
      const y = 40 / 2;
      const keyShape = group.addShape("rect", {
        attrs: {
          x: x + 0,
          y: y + 0,
          width: 222,
          height: 40,
          fill: backGrounfColor,
          stroke: displayStatus ? borderColor : "#ECEDF3",
          // radius: 4,
          cursor: "pointer",
        },
        name: "card-node-keyShape",
      });
      // eslint-disable-next-line no-unused-vars
      const image = group.addShape("image", {
        attrs: {
          x: x + 5,
          y: y + 12,
          width: 16,
          height: 16,
          img: img,
          cursor: "pointer",
        },
        name: "card-node-image",
      });
      // eslint-disable-next-line no-unused-vars
      const nodeName = group.addShape("text", {
        attrs: {
          x: x + 25,
          y: y + 14,
          // stroke: "#ECEDF3",
          fill: "#333",
          fontSize: 14,
          // text: cfg.nodeName,
          text:
            truncateString(cfg.nodeName).length > 18
              ? truncateString(cfg.nodeName).result + "..."
              : truncateString(cfg.nodeName).result,
          textBaseline: "top",
          cursor: "pointer",
        },
        name: "card-node-nodeName",
      });
      // eslint-disable-next-line no-unused-vars
      const batch = group.addShape("text", {
        attrs: {
          x: x + 180,
          y: y + 14,
          // stroke: "#ECEDF3",
          fill: "#666",
          fontSize: 14,
          text: cfg.batch,
          textBaseline: "top",
          cursor: "pointer",
        },
        name: "card-node-batch",
      });
      if (len > 1) {
        // eslint-disable-next-line no-unused-vars
        const nodeFlow = group.addShape("circle", {
          attrs: {
            x: x + 222,
            y: y + 0,
            r: rLen,
            stroke: "#C73320",
            fill: "#C73320",
          },
          name: "card-node-nodeFlow",
        });
        // eslint-disable-next-line no-unused-vars
        const length = group.addShape("text", {
          attrs: {
            x: x + xPosition,
            y: y + 7,
            // stroke: "#ECEDF3",
            fill: "#fff",
            fontSize: 12,
            text: len,
          },
          name: "card-node-length",
        });
      }
      return keyShape;
    },
    update: undefined,
  },
  "rect"
);
// 注册combo的自定义绘制
G6.registerCombo("custom-combo", {
  draw(cfg, group) {
    // 绘制combo的容器，这里使用rect
    const rect = group.addShape("rect", {
      attrs: {
        x: -150, // 偏移量，确保combo的中心与rect的中心对齐
        y: -300, // 同上
        width: 300, // 宽度
        height: 800, // 高度
        fill: "#F9FAFD", // 背景色
        stroke: "#c91717", // 边框色
        lineWidth: 1, // 边框宽度
        label: cfg.label,
      },
      name: "combo-rect", // 可选：自定义名称，用于后续引用或查找
    });

    // 如果你需要绘制combo的label或其他元素，可以在这里添加
    // ...

    return rect;
  },
  // 可选：定义combo的更新逻辑
  update(cfg, item) {
    // 在combo更新时执行的操作
    // ...
  },
});
export default {
  name: "overall-link",
  data() {
    return {
      currentTime: moment().format("YYYY-MM-DD HH:mm:ss"),
      labelCol: {
        style: {
          width: "64px",
        },
      },
      modelLevel: undefined, //层级入参
      modelCode: undefined, //模型名称入参
      // dateType: "D", //模型账期入参
      modelCodeData: [], //下拉框数据
      legend: [
        {
          modelLevel: "1",
          name: "采集层",
          backGroundColor: "#E1D2FF",
          border: "1px #F22929 solid",
        },
        {
          modelLevel: "2",
          name: "数仓层",
          backGroundColor: "#FFEDDB",
          border: "1px #FFC510 solid",
        },
        {
          modelLevel: "3",
          name: "集市层",
          backGroundColor: "#D0F2D9",
          border: "1px #02B32E solid",
        },
        {
          modelLevel: "4",
          name: "应用层",
          backGroundColor: "#C6E3FF",
          border: "1px #1890FF solid",
        },
      ],
      logoList: [
        {
          name: "已完成",
          img: finished,
        },
        {
          name: "进行中",
          img: process,
        },
        {
          name: "未完成",
          img: unfinished,
        },
        {
          name: "未开始",
          img: unStart,
        },
        {
          name: "延迟",
          img: delay,
        },
        {
          name: "已恢复",
          img: recover,
        },
      ],
      nodeData: {
        nodes: [],
        edges: [],
        combos: [],
      },
      graph: null,
      pageNo: 1,
      pageSize: 10,
      keyword: "", //搜索关键词
      datasourceList: [],
      spinning: true,
      status: false,
    };
  },
  components: {
    CommonLoading,
  },
  async created() {
    await this.getModelLevelData();
    this.modelLevel = this.$route.query.modelLevel || undefined;
    this.modelCode = this.$route.query.modelCode || undefined;
    this.status = this.$route.query?.status === "true" ? true : false;

    // this.dateType = this.$route.query.dateType || "D";
    if (this.modelLevel && this.modelCode) {
      this.$refs.commonLoading?.show();
      await this.getDatasourceList(); //获取模型名称
      this.getProcessData();
    }
  },
  computed: {
    dateType() {
      let str = "";
      if (this.datasourceList && this.datasourceList.length) {
        this.datasourceList.forEach((item) => {
          if (item.modelCode == this.modelCode) {
            str = item.dateType;
          }
        });
      }
      return str;
    },
    // modelCodeNameData() {
    //   let array = [];
    //   if (this.modelCodeData && this.modelCodeData.length) {
    //     this.modelCodeData.forEach((item) => {
    //       if (item.modelLevel == this.modelLevel) {
    //         array = item.children;
    //       }
    //     });
    //   }
    //   return array;
    // },
  },
  watch: {
    nodeData: {
      handler(newVal, oldVal) {
        if (isEqual(newVal, oldVal) === false) {
          this.graph.read({ ...newVal });
          this.graph.refreshPositions();
        }
      },
      deep: true,
    },
    modelCode() {
      if (!this.modelCode) {
        this.modelCode = undefined;
        this.datasourceList = [];
        this.pageNo = 1;
        this.pageSize = 10;
        this.getDatasourceList();
      }
    },
  },
  methods: {
    returnRoute() {
      this.$router.back();
      this.$emit("routerAction", "marketIndicatorAudit");
    },
    async getDatasourceList() {
      let queryparams = {
        modelLevel: this.modelLevel,
        modelName: this.keyword,
        modelCode: this.modelCode || "",
        pageNo: this.pageNo,
        pageSize: this.pageSize,
      };
      await getModelCodeData(queryparams).then((response) => {
        this.datasourceCount = response?.data?.total;
        if (this.datasourceList.length <= this.datasourceCount) {
          this.datasourceList = this.datasourceList.concat(
            response?.data?.list
          );
        }
      });
    },
    // 列表滚动时加载数据scrollTop指的就是整体往上滑动的距离,scrollHeight指的是用户可以看到的所有的东西的高度,clientHeight代表了内容区域的高度
    handlePopupScroll(e) {
      const { target } = e;
      const { scrollTop, scrollHeight, clientHeight } = target;
      if (
        scrollTop + 2 + clientHeight >= scrollHeight &&
        this.pageNo * this.pageSize < this.datasourceCount
      ) {
        // 已经到达底部，触发分页逻辑
        // todo 这里就可以触发加载下一页请求  具体函数根据当前业务需求来定
        this.pageNo += 1;
        this.getDatasourceList();
      }
    },
    // 选中 option 调用
    clickLdapOpt(val) {
      if (!val) {
        this.keyword = "";
      }
      this.modelCode = val;
    },
    // 文本框值变化时回调
    filterOpts(val) {
      this.keyword = val;
      this.datasourceList = [];
      this.pageNo = 1;
      this.pageSize = 10;
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.getDatasourceList();
      }, 500);
      // if (this.keyword) {
      //   clearTimeout(this.timer);
      //   this.timer = setTimeout(() => {
      //     this.getDatasourceList();
      //   }, 500);
      // } else {
      //   this.getDatasourceList();
      // }
    },
    // modelNameChange(item, modelCode) {
    //   console.log(item);
    //   console.log(modelCode);
    // },
    searchData: debounce(function () {
      this.$refs.commonLoading?.show();
      this.getProcessData();
      this.currentTime = moment().format("YYYY-MM-DD HH:mm:ss");
    }, 500),
    async getModelLevelData() {
      let res = await getModelLevelData();
      if (res && res.code == "200") {
        this.modelCodeData = res.data;
      }
    },
    modelLevelChange() {
      this.modelCode = undefined;
      this.keyword = "";
      this.datasourceList = [];
      this.pageNo = 1;
      this.pageSize = 10;
      this.getDatasourceList();
    },
    clearData() {
      this.$refs.commonLoading?.show();
      this.modelLevel = undefined;
      this.modelCode = undefined;
      this.getProcessData();
    },
    async getProcessData() {
      try {
        const res = await queryNodeData({
          modelLevel: this.modelLevel || "",
          // modelLevel: "4",
          modelCode: this.modelCode || "",
          // modelCode: "14286609",
          dateType: this.dateType,
          // dateType: "D",
        });
        if (res.code == 200) {
          const childNodeCountMap = {};
          res.data.nodes.forEach((node) => {
            node.comboId = `combo-${node.modelLevel}`;
            childNodeCountMap[node.comboId] =
              childNodeCountMap[node.comboId] || 0;
            childNodeCountMap[node.comboId]++;
          });
          let arr = [];
          this.modelCodeData.forEach((item) => {
            if (childNodeCountMap[`combo-${item.modelLevel}`]) {
              arr.push({
                id: `combo-${item.modelLevel}`,
                label: item.modelName,
              });
            }
          });
          res.data.combos = arr;
          this.nodeData = res.data;
        }
      } catch (error) {
        console.log(error);
      }
      this.$refs.commonLoading?.hidden();
    },
    createMyProcess(data) {
      const tooltip1 = new G6.Tooltip({
        itemTypes: ["node"],
        getContent(e) {
          return e.item.getModel().nodeName || "";
        },
      });
      const tooltip = new G6.Tooltip({
        itemTypes: ["node"],
        trigger: "click",
        getContent(e) {
          // return e.item.getModel().nodeName || "";
          const flow = e.item.getModel()?.flow || [];
          if (flow.length === 0) {
            const outDiv = document.createElement("div");
            outDiv.style.width = "220px";
            outDiv.style.height = "30px";
            return outDiv;
          } else {
            const outDiv = document.createElement("div");
            outDiv.style.width = "220px";
            outDiv.style.maxHeight = "400px";
            outDiv.style.overflow = "hidden";
            outDiv.style.overflowY = "scroll";
            let html = "";
            flow.forEach((item) => {
              let logo = getImg(item.flowStatus);
              html += `<div title="${item.flowName}" style="display: flex;align-items: center;gap:5px;margin-bottom: 5px; cursor: pointer"><img src="${logo}" alt=""><span style="max-width: 195px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;font-size: 14px">${item.flowName}</span></div>`;
            });
            outDiv.innerHTML = html;
            return outDiv;
          }
        },
      });
      const container = this.$refs.container;
      const screenWidth = container.scrollWidth || 500;
      const screenHeight = container.scrollHeight || 500;
      this.graph = new G6.Graph({
        container: container,
        width: screenWidth,
        height: screenHeight,
        controlPoints: false,
        modes: {
          default: ["drag-canvas", "zoom-canvas"],
          //不可拖拽
          // default: [],
        },
        fitView: true,
        layout: {
          type: "dagre",
          rankdir: "LR",
          // align: "DL",
          // align: "UL",
          nodesep: 16,
          ranksep: 100,
        },

        // animate: true,
        defaultNode: {
          type: "card-node",
        },
        defaultCombo: {
          labelCfg: {
            style: {
              fill: "#212743",
              fontSize: 16,
              fontWeight: "bold",
            },
          },
          // type: "custom-combo",
          type: "rect",
          padding: [50, 20, 15, 10],
          style: {
            fill: "#F9FAFD",
            stroke: "#c91717",
          },
        },
        defaultEdge: {
          size: 1,
          color: "#AFB3C3",
          style: {
            // lineDash: [2, 2],
            endArrow: {
              path: "M 0,0 L 8,4 L 8,-4 Z",
              fill: "#AFB3C3",
            },
          },
        },
        plugins: [tooltip1, tooltip],
      });
      this.graph.on("card-node-keyShape:click", (e) => {
        const { item, target } = e;
        // getModel方法获取cfg里面的数据信息
        console.log(
          target.get("modelId"),
          item.getModel().id,
          item.getModel().nodeName,
          "点击"
        );
      });
      this.graph.data(data);
      this.graph.render();
      // this.graph.fitView();
    },
  },
  async mounted() {
    this.createMyProcess(this.nodeData);
  },
  beforeDestroy() {},
};
</script>
<style scoped lang="less">
.all-page {
  font-size: 14px;
  background-color: #f3f6fa;
  padding: 16px 16px 0 16px;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;

  .search {
    width: 100%;
    height: 73px;
    background-color: #fff;
    margin-bottom: 16px;
    padding: 16px 16px;
    border-bottom: 1px solid #e9edf3;
    .overall-link-condition {
      display: flex;
      align-items: center;
      background: #ffffff;
      //margin: 16px 24px;
      //padding: 24px 24px 24px 60px;

      .form-style {
        position: relative;
      }
      .select-style {
        width: 220px;
      }
      /* 查询和导出 */
      .all-btn {
        display: flex;
        margin-left: auto;
        margin-right: 0px;
        .condition-btn {
          display: flex;
          align-items: center;
          justify-content: center;
          width: 60px;
          height: 32px;
          margin-top: 4px;
          color: #ffffff;
          background-color: #c91717;
          border-radius: 4px;
          cursor: pointer;
        }
        .gap {
          color: #6b6b6b;
          margin-left: 8px;
          background: white;
          border: 1px solid #c8c8c8;
        }
      }

      //查询栏选择器字体颜色
      /deep/ .ant-select {
        color: rgba(0, 0, 0, 0.85);
      }
      /deep/ .ant-input {
        color: rgba(0, 0, 0, 0.85);
      }

      /deep/.ant-form label {
        font-size: 14px;
        font-weight: 400;
        color: #4f5769;
        line-height: 20px;
      }
    }
  }
  .page-content {
    position: relative;
    height: calc(100% - 50px);
    width: 100%;
    background-color: #fff;
    display: flex;
    flex-direction: column;
    padding: 16px;
    .loading-position {
      position: absolute;
      // z-index: 999;
    }
    .legend {
      margin-bottom: 16px;
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: space-between;
      .photo-logo {
        display: flex;
        align-items: center;
        gap: 16px;
        &-item {
          font-size: 14px;
          img {
            margin-right: 5px;
            padding-bottom: 2px;
          }
        }
      }
      .legend-logo {
        display: flex;
        align-items: center;
        gap: 16px;
        .current-tiem {
          color: #333333;
        }
        &-item {
          font-size: 14px;
          display: flex;
          align-items: center;
          gap: 5px;
          .rectangle {
            width: 16px;
            height: 16px;
          }
        }
      }
    }
    .process {
      width: 100%;
      //height: calc(100% - 73px);
      height: 100%;
      //overflow-y: auto;
      padding: 0 16px;
      font-size: 14px;
      color: #333;
      //border: 1px red solid;
      overflow: auto;
      .content {
        width: 100%;
        height: 100%;
        //border: 1px green solid;
      }
    }
  }
}
</style>
